home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / comm / misc / CapiRexxVoiceM.lha / bchanneljobs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-08  |  11.6 KB  |  632 lines

  1. /*
  2. **
  3. **    $Id: bchanneljobs.c,v 1.1 1995/07/13 02:53:15 chris Exp $
  4. **    $Revision: 1.1 $
  5. **
  6. **    $Filename: developer/bchanneljobs.c $
  7. **    $Author: chris $
  8. **    $Date: 1995/07/13 02:53:15 $ 
  9. **    $Portability: ANSI $
  10. **
  11. **    B-Kanal Lese/Schreibjobs
  12. **
  13. **    THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF RELOG AG.
  14. **
  15. **    COPYRIGHT (C) 1992-1995 BY RELOG AG, ZUERICH. ALL RIGHTS RESERVED.
  16. **    NO PART OF THIS SOFTWARE MAY BE COPIED, REPRODUCED, OR TRANSMITTED
  17. **    IN ANY FORM OR BY ANY MEANS,  WITHOUT THE PRIOR WRITTEN PERMISSION
  18. **    OF RELOG AG.
  19. **
  20. */
  21.  
  22. #include "os.h"
  23. #include "capi-usr.h"
  24.  
  25. #define _BCHANNELJOBS
  26. #include "bchanneljobs.h"
  27. #include "alaw.h"
  28. #include "am.h"
  29. #include "process.h"
  30.  
  31.  
  32. static U8    __far tempbuf8[B_BLOCKSIZE];
  33. static S16    __far tempbuf16[B_BLOCKSIZE];
  34. static S16    __far mixbuf16[B_BLOCKSIZE];
  35.  
  36.  
  37. /*
  38. **    Sound mixen, volume = 0..B_VOLUME_MAX
  39. */
  40. static U16 MixIn( S16 *from, S16 *to, U16 len, U16 volume, U16 endvolume )
  41. {
  42.     while (len)
  43.     {
  44. #if 1
  45.         S32 s = (((S32)*from++ * volume) >> B_VOLUME_SHIFT) + *to;
  46. #else
  47.         S32 s = (S32)*from++ + *to;
  48. #endif
  49.  
  50.         if (s < -32768)
  51.             s = -32768;
  52.  
  53.         if (s > 32767)
  54.             s = 32767;
  55.  
  56.         *to++ = (S16)s;
  57.  
  58.  
  59.         /*
  60.         **    Der megacoole Fader
  61.         */
  62.         if (volume > endvolume)
  63.             volume--;
  64.         else if (volume < endvolume)
  65.             volume++;
  66.  
  67.  
  68.         len--;
  69.     }
  70.  
  71.     return volume;
  72. }
  73.  
  74.  
  75. /*
  76. **    Einsprung des File I/O-Prozesses eines B-Kanals
  77. */
  78. static BOOL __saveds IOProcFunc( struct BChannel *bc )
  79. {
  80.     struct BChannel_Job    *job;
  81.     static                S16 inuse;
  82.  
  83.     /*
  84.     **    Sicherstellen, dass wir nicht 2x gleichzeitig laufen
  85.     */
  86.     if (++inuse > 1)
  87.     {
  88.         inuse--;
  89.         return TRUE;
  90.     }
  91.  
  92.  
  93.     /*
  94.     **    Alle Jobs abarbeiten
  95.     */
  96. redo:
  97.     DOLIST( &bc->JobList, job )
  98.     {
  99.         struct Buffer *buf = job->PlayBuffer;
  100.  
  101.         if (buf->EndOfFile)
  102.             continue;
  103.  
  104.         if (job->Flags & JOBF_WRITE)                /* File --> B-Kanal */
  105.         {
  106.             if (buf->ActLength == 0)                /* Puffer leer ? */
  107.             {
  108.                 U16 rest;
  109.  
  110. /*                printf( "Reading %ld bytes\n", (U32)buf->TotalLength ); */
  111.                 buf->Position  = buf->Data;
  112.                 buf->ActLength = (U16)fread( buf->Data, 1, buf->TotalLength, job->File );
  113.  
  114.                 rest = buf->TotalLength - buf->ActLength;
  115.                 if (rest && (job->Flags & JOBF_LOOP))
  116.                 {
  117. /*                    printf( "Rewinding file.\n" ); */
  118.                     rewind( job->File );
  119.                     buf->ActLength += fread( buf->Data + buf->ActLength, 1, rest, job->File );
  120.                 }
  121.  
  122.                 if (buf->ActLength == 0)
  123.                     buf->EndOfFile = TRUE;
  124.  
  125.                 goto redo;
  126.             }
  127.         }
  128.         else if (job->Flags & JOBF_READ)            /* B-Kanal --> File */
  129.         {
  130.             if (buf->ActLength == buf->TotalLength)    /* Puffer voll ? */
  131.             {
  132.                 buf->Position  = buf->Data;
  133. /*                printf( "Writing file\n" ); */
  134.                 fwrite( buf->Data, 1, buf->ActLength, job->File );
  135.                 buf->ActLength = 0;
  136.  
  137.                 goto redo;
  138.             }
  139.         }
  140.     }
  141.  
  142.     inuse--;
  143.     return TRUE;
  144. }
  145.  
  146.  
  147. /****** BChannel_New ********************************************************
  148. *
  149. *   NAME
  150. *       BChannel_New -- Create a new B-channel entity
  151. *
  152. *   SYNOPSIS
  153. *       channel = BChannel_New( ncci )
  154. *
  155. *       struct BChannel *BChannel_New( U32 );
  156. *
  157. *   FUNCTION
  158. *
  159. *   INPUTS
  160. *
  161. *   RESULTS
  162. *
  163. *   SEE ALSO
  164. *
  165. ****************************************************************************/
  166.  
  167. struct BChannel *
  168. BChannel_New( U32 NCCI )
  169. {
  170.     struct BChannel *bc;
  171.  
  172.     if ((bc = OS_Malloc( sizeof( *bc ) )) != NULL)
  173.     {
  174.         bc->NCCI = NCCI;
  175.  
  176.         NEWLIST( &bc->JobList );
  177.  
  178.         if (bc->IOProcess = Process_Create( IOProcFunc, bc, "AM-IO", 4 ))
  179.         {
  180.             USES_DISABLE
  181.  
  182.             bc->Buf1.Position = bc->Buf1.Data;
  183.             bc->Buf2.Position = bc->Buf2.Data;
  184.             bc->Buf1.TotalLength = sizeof( bc->BD1 );
  185.             bc->Buf2.TotalLength = sizeof( bc->BD2 );
  186.  
  187.             bc->WriteBuffer    = &bc->Buf1;
  188.             bc->PlayBuffer    = &bc->Buf2;
  189.  
  190.             DISABLE;
  191.             ADDTAIL( &bchannellist, &bc->Node );
  192.             ENABLE;
  193.         }
  194.         else
  195.         {
  196.             printf( "Can't create B-channel I/O process\n" );
  197.             OS_Free( bc );
  198.             bc = NULL;
  199.         }
  200.     }
  201.  
  202.     return bc;
  203. }
  204.  
  205.  
  206. /****** BChannel_Free *******************************************************
  207. *
  208. *   NAME
  209. *       BChannel_Free -- Free a B-channel entity
  210. *
  211. *   SYNOPSIS
  212. *       BChannel_Free( bc )
  213. *
  214. *       VOID BChannel_Free( struct BChannel * );
  215. *
  216. *   FUNCTION
  217. *
  218. *   INPUTS
  219. *
  220. *   RESULTS
  221. *
  222. *   SEE ALSO
  223. *
  224. ****************************************************************************/
  225.  
  226. VOID
  227. BChannel_Free( struct BChannel *bc )
  228. {
  229.     if (bc != NULL)
  230.     {
  231.         USES_DISABLE
  232.  
  233.         DISABLE;
  234.  
  235.         while (!ISLISTEMPTY( &bc->JobList))
  236.         {
  237.             BChannel_FreeJob( (struct BChannel_Job *)bc->JobList.Head );
  238.         }
  239.  
  240.         REMOVE( &bc->Node );
  241.  
  242.         Process_Delete( bc->IOProcess );
  243. /*        bc->IOProcess = NULL; */
  244.  
  245.         ENABLE;
  246.  
  247.         OS_Free( bc );
  248.     }
  249. }
  250.  
  251.  
  252. /****** BChannel_Find *******************************************************
  253. *
  254. *   NAME
  255. *       BChannel_Find -- Find a B-channel entity by its NCCI
  256. *
  257. *   SYNOPSIS
  258. *       bc = BChannel_Find( ncci )
  259. *
  260. *       struct BChannel *BChannel_Find( U32 );
  261. *
  262. *   FUNCTION
  263. *
  264. *   INPUTS
  265. *
  266. *   RESULTS
  267. *
  268. *   SEE ALSO
  269. *
  270. ****************************************************************************/
  271.  
  272. struct BChannel *
  273. BChannel_Find( U32 ncci )
  274. {
  275.     struct BChannel *bc, *result = NULL;
  276.     USES_DISABLE
  277.  
  278.     DISABLE;
  279.  
  280.     DOLIST( &bchannellist, bc )
  281.     {
  282.         if (bc->NCCI == ncci)
  283.         {
  284.             result = bc;
  285.             break;
  286.         }
  287.     }
  288.  
  289.     ENABLE;
  290.  
  291.     return result;
  292. }
  293.  
  294.  
  295. /****** BChannel_AddJob *****************************************************
  296. *
  297. *   NAME
  298. *       BChannel_AddJob -- Add a read/write job to a B-channel
  299. *
  300. *   SYNOPSIS
  301. *       bc = BChannel_AddJob( bc, filename, flags, U16 volume, sigproc )
  302. *
  303. *       struct BChannel_Job *BChannel_AddJob( struct BChannel *,
  304. *                                             U8 *, U16, U16, U32 );
  305. *
  306. *   FUNCTION
  307. *
  308. *   INPUTS
  309. *       bc       - B-channel to add job to
  310. *       filename - File to read / write data
  311. *       flags    - JOBF_...
  312. *       volume   - 0..B_VOLUME_MAX
  313. *       sigproc  - Process to signal when the job is terminated
  314. *
  315. *   RESULTS
  316. *
  317. *   SEE ALSO
  318. *
  319. ****************************************************************************/
  320.  
  321. struct BChannel_Job *
  322. BChannel_AddJob( struct BChannel *bc, U8 *filename, U16 flags, U16 volume, U32 sigproc )
  323. {
  324.     if ((bc != NULL) && (filename != NULL))
  325.     {
  326.         struct BChannel_Job *job;
  327.  
  328. /*        printf( "Adding %s job '%s'\n", (flags & JOBF_READ) ? "READ" : "WRITE", filename ); */
  329.  
  330.         if ((job = OS_Malloc( sizeof( *job ) )) != NULL)
  331.         {
  332.             job->Flags        = flags;
  333.             job->ActVolume    = volume;
  334.             job->EndVolume    = volume;
  335.             job->SigProc    = sigproc;
  336.  
  337.             job->Buf1.Position = job->Buf1.Data;
  338.             job->Buf2.Position = job->Buf2.Data;
  339.             job->Buf1.TotalLength = sizeof( job->BD1 );
  340.             job->Buf2.TotalLength = sizeof( job->BD2 );
  341.  
  342.             job->BChannel        = bc;
  343.  
  344.             job->WriteBuffer    = &job->Buf1;
  345.             job->PlayBuffer        = &job->Buf2;
  346.  
  347.             if (job->File = fopen( filename, (flags & JOBF_WRITE) ? "r" : "w" ))
  348.             {
  349.                 BOOL firsttime = ISLISTEMPTY( &bc->JobList );
  350.                 USES_DISABLE;
  351.  
  352.                 setbuf( job->File, NULL );                /* Unbuffered i/o */
  353.  
  354.                 DISABLE;
  355.                 ADDTAIL( &bc->JobList, &job->Node );
  356.                 ENABLE;
  357.  
  358.                 IOProcFunc( bc );                    /* Daten des neuen Files lesen */
  359.  
  360.                 if (firsttime)
  361.                 {
  362.                     BChannel_DataB3Conf( bc->NCCI );    /* 2x für Doublebuffering */
  363.                     BChannel_DataB3Conf( bc->NCCI );
  364.                 }
  365.  
  366.                 return job;
  367.             }
  368.             else
  369.             {
  370.                 printf( "Can't open file '%s'\n", filename );
  371.             }
  372.  
  373.             OS_Free( job );
  374.         }
  375.     }
  376.  
  377.     return NULL;
  378. }
  379.  
  380.  
  381. /****** BChannel_FreeJob ****************************************************
  382. *
  383. *   NAME
  384. *       BChannel_FreeJob -- Free a read/write job
  385. *
  386. *   SYNOPSIS
  387. *       BChannel_FreeJob( bc )
  388. *
  389. *       VOID BChannel_FreeJob( struct BChannel * );
  390. *
  391. *   FUNCTION
  392. *       Removes the job if it's in the job list, and frees its resources.
  393. *
  394. *   INPUTS
  395. *
  396. *   RESULTS
  397. *
  398. *   SEE ALSO
  399. *
  400. ****************************************************************************/
  401.  
  402. VOID
  403. BChannel_FreeJob( struct BChannel_Job *job )
  404. {
  405.     if (job != NULL)
  406.     {
  407.         USES_DISABLE
  408.  
  409.         DISABLE;
  410.         if (job->Node.Succ != NULL)
  411.         {
  412.             REMOVE( &job->Node );
  413.             job->Node.Succ = NULL;
  414.         }
  415.         ENABLE;
  416.  
  417.         if (job->File != NULL)
  418.         {
  419.             fclose( job->File );
  420. /*            job->File = NULL; */
  421.         }
  422.  
  423.         if (job->SigProc)
  424.         {
  425.             Process_WakeUp( job->SigProc );
  426.         }
  427.  
  428.         OS_Free( job );
  429.     }
  430. }
  431.  
  432.  
  433. /****** BChannel_DataB3Ind **************************************************
  434. *
  435. *   NAME
  436. *       BChannel_DataB3Ind -- Handle incoming data
  437. *
  438. *   SYNOPSIS
  439. *       BChannel_DataB3Ind( ncci, data, length )
  440. *
  441. *       VOID BChannel_DataB3Ind( U32, U8 *, U16 );
  442. *
  443. *   FUNCTION
  444. *
  445. *   INPUTS
  446. *
  447. *   RESULTS
  448. *
  449. *   SEE ALSO
  450. *
  451. ****************************************************************************/
  452.  
  453. VOID
  454. BChannel_DataB3Ind( U32 ncci, U8 *data, U16 length )
  455. {
  456.     struct BChannel *bc;
  457.  
  458.     if (bc = BChannel_Find( ncci ))
  459.     {
  460.         struct BChannel_Job    *job;
  461.         BOOL                work = FALSE;
  462.  
  463.         DOLIST( &bc->JobList, job )
  464.         {
  465.             if (job->Flags & JOBF_READ)
  466.             {
  467.                 struct Buffer    *buf = job->WriteBuffer;
  468.                 U16                wlen = buf->TotalLength - buf->ActLength;
  469.  
  470.                 if (wlen > length)
  471.                     wlen = length;
  472.  
  473.                 OS_memcpy( buf->Position, data, wlen );
  474.                 buf->Position  += wlen;
  475.                 data += wlen;
  476.                 buf->ActLength += wlen;
  477.  
  478.                 length -= wlen;
  479.  
  480.                 if (buf->ActLength == buf->TotalLength)        /* Puffer voll ? */
  481.                 {
  482.                     job->WriteBuffer = job->PlayBuffer;        /* Swap */
  483.                     job->PlayBuffer  = buf;
  484.                     buf = job->WriteBuffer;
  485.  
  486.                     buf->Position  = buf->Data;                /* Neuen Buffer leeren */
  487.                     buf->ActLength = 0;
  488.  
  489.                     if (length)
  490.                     {
  491.                         OS_memcpy( buf->Position, data, length );
  492.                         buf->Position  += length;
  493.                         buf->ActLength += length;
  494.                     }
  495.  
  496.                     work = TRUE;
  497.                 }
  498.             }
  499.         }
  500.  
  501.         if (work)
  502.             Process_WakeUp( bc->IOProcess );
  503.     }
  504. }
  505.  
  506.  
  507. /****** BChannel_DataB3Conf *************************************************
  508. *
  509. *   NAME
  510. *       BChannel_DataB3Conf -- Handle acknowledgement of outgoing data
  511. *
  512. *   SYNOPSIS
  513. *       BChannel_DataB3Conf( ncci )
  514. *
  515. *       VOID BChannel_DataB3Conf( U32 );
  516. *
  517. *   FUNCTION
  518. *
  519. *   INPUTS
  520. *
  521. *   RESULTS
  522. *
  523. *   SEE ALSO
  524. *
  525. ****************************************************************************/
  526.  
  527. VOID
  528. BChannel_DataB3Conf( U32 ncci )
  529. {
  530.     struct BChannel *bc;
  531.  
  532.     if (bc = BChannel_Find( ncci ))
  533.     {
  534.         struct BChannel_Job    *job;
  535.         BOOL                work = FALSE;
  536.  
  537.         struct
  538.         {
  539.             CAPI_MESSAGE    Msg;
  540.             U8                Para[14];
  541.         } data_b3_req;
  542.  
  543.         U8 *para = data_b3_req.Para;
  544.  
  545.  
  546.         OS_memset( mixbuf16, 0, sizeof( mixbuf16 ) );
  547.  
  548.  
  549.         /*
  550.         **    Daten aller Jobs zusammenmischen
  551.         */
  552.  
  553.         DOLIST( &bc->JobList, job )
  554.         {
  555.             if (job->State == JOBSTATE_TERMINATED)
  556.                 continue;
  557.  
  558.             if (job->Flags & JOBF_WRITE)
  559.             {
  560.                 struct Buffer    *buf = job->WriteBuffer;
  561.                 U16                wlen = buf->ActLength;
  562.  
  563.                 if (wlen > B_BLOCKSIZE)
  564.                     wlen = B_BLOCKSIZE;
  565.  
  566.                 ALAW_ALawTo16Bit( buf->Position, tempbuf16, (U32)wlen );
  567.                 buf->Position  += wlen;
  568.                 buf->ActLength -= wlen;
  569.  
  570.                 job->ActVolume = MixIn( tempbuf16, mixbuf16, wlen, job->ActVolume, job->EndVolume );
  571.  
  572.                 if (buf->ActLength == 0)                    /* Puffer leer ? */
  573.                 {
  574.                     job->WriteBuffer = job->PlayBuffer;        /* Swap */
  575.                     job->PlayBuffer  = buf;
  576.                     buf = job->WriteBuffer;
  577.  
  578.                     if (buf->EndOfFile)                        /* Keine Daten mehr */
  579.                     {
  580.                         if (job->Flags & JOBF_AUTOFREE)
  581.                         {
  582.                             struct BChannel_Job *oldjob = job;
  583.                             job = (struct BChannel_Job *)oldjob->Node.Pred;
  584.                             BChannel_FreeJob( oldjob );
  585.                         }
  586.                         else
  587.                         {
  588.                             job->State = JOBSTATE_TERMINATED;
  589.                         }
  590.                     }
  591.  
  592.                     work = TRUE;
  593.                 }
  594.             }
  595.         }
  596.  
  597.         ALAW_16BitToALaw( mixbuf16, bc->WriteBuffer->Data, (U32)bc->WriteBuffer->TotalLength );
  598.  
  599.  
  600.         /*
  601.         **    DATA_B3_REQ absenden
  602.         */
  603.         data_b3_req.Msg.Command        = CAPICMD_DATA_B3;
  604.         data_b3_req.Msg.Subcommand    = CAPISUBCMD_REQ;
  605.  
  606.         ADD_PARA( para, U32,    bc->NCCI );
  607.         ADD_PARA( para, U8 *,    bc->WriteBuffer->Data );
  608.         ADD_PARA( para, U16,    bc->WriteBuffer->TotalLength );
  609.         ADD_PARA( para, U16,    0x1234 );            /* Data handle */
  610.         ADD_PARA( para, U16,    0 );                /* Flags */
  611.  
  612.         SendCAPIMessage( &data_b3_req.Msg, para );
  613.  
  614.  
  615.         /*
  616.         **    Double buffering
  617.         */
  618.         {
  619.             struct Buffer *tmp = bc->WriteBuffer;
  620.             bc->WriteBuffer = bc->PlayBuffer;
  621.             bc->PlayBuffer = tmp;
  622.         }
  623.  
  624.         if (work)
  625.         {
  626. /*            printf( "DataB3Conf: waking up I/O process 0x%08lx\n", bc->IOProcess ); */
  627.             Process_WakeUp( bc->IOProcess );
  628.         }
  629.     }
  630. }
  631.  
  632.